home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / misc1 / iv26_w30.zip / SOURCES / PAINTER.C < prev    next >
C/C++ Source or Header  |  1992-02-25  |  16KB  |  616 lines

  1. /*
  2.  * Copyright (c) 1987, 1988, 1989 Stanford University
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided
  6.  * that the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of Stanford not be used in advertising or
  9.  * publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.  Stanford makes no representations about
  11.  * the suitability of this software for any purpose.  It is provided "as is"
  12.  * without express or implied warranty.
  13.  *
  14.  * STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
  16.  * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  19.  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  20.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  21.  */
  22.  
  23. /*
  24.  * Graphics primitives.
  25.  */
  26.  
  27. #include <InterViews/brush.h>
  28. #include <InterViews/color.h>
  29. #include <InterViews/font.h>
  30. #include <InterViews/painter.h>
  31. #include <InterViews/pattern.h>
  32. #ifdef _3D
  33. #include <InterViews/canvas.h>
  34. #endif
  35. #include <InterViews/transformer.h>
  36. #include <string.h>
  37.  
  38. /*
  39.  * For reasons of caching, it is important that the attributes
  40.  * are set to nil (or 0) before being set to their default values.
  41.  * Also, it is important that the colors are set before the fill pattern.
  42.  */
  43.  
  44. void Painter::Init () {
  45.     if (solid == nil) {
  46.     solid = new Pattern(0xffff);
  47.     solid->Reference();
  48.     clear = new Pattern(0);
  49.     clear->Reference();
  50.     lightgray = new Pattern(0x8020);
  51.     lightgray->Reference();
  52.     gray = new Pattern(0xa5a5);
  53.     gray->Reference();
  54.     darkgray = new Pattern(0xfafa);
  55.     darkgray->Reference();
  56.     single = new Brush(0xffff, 0);
  57.     single->Reference();
  58.     }
  59.     foreground = nil;
  60.     background = nil;
  61.     pattern = nil;
  62.     br = nil;
  63.     dash = nil;
  64.     font = nil;
  65.     style = 0;
  66.     matrix = nil;
  67.     SetColors(black, white);
  68.     SetPattern(solid);
  69.     FillBg(true);
  70.     SetBrush(single);
  71.     SetFont(stdfont);
  72.     SetStyle(Plain);
  73.     SetOrigin(0, 0);
  74.     MoveTo(0, 0);
  75. }
  76.  
  77. void Painter::Copy (Painter* copy) {
  78.     foreground = nil;
  79.     background = nil;
  80.     pattern = nil;
  81.     br = nil;
  82.     dash = nil;
  83.     font = nil;
  84.     style = 0;
  85.     matrix = nil;
  86.     SetColors(copy->foreground, copy->background);
  87.     SetPattern(copy->pattern);
  88.     SetBrush(copy->br);
  89.     SetFont(copy->font);
  90.     SetStyle(copy->style);
  91.     SetTransformer(copy->matrix);
  92.     SetOrigin(copy->xoff, copy->yoff);
  93.     MoveTo(copy->curx, copy->cury);
  94. }
  95.  
  96. Color* Painter::GetFgColor () {
  97.     return foreground;
  98. }
  99.  
  100. Color* Painter::GetBgColor () {
  101.     return background;
  102. }
  103.  
  104. Pattern* Painter::GetPattern () {
  105.     return pattern;
  106. }
  107.  
  108. Brush* Painter::GetBrush () {
  109.     return br;
  110. }
  111.  
  112. Font* Painter::GetFont () {
  113.     return font;
  114. }
  115.  
  116. void Painter::SetStyle (int s) {
  117.     style = s;
  118. }
  119.  
  120. int Painter::GetStyle () {
  121.     return style;
  122. }
  123.  
  124. void Painter::SetTransformer (Transformer *t) {
  125.     if (matrix != t) {
  126.     Unref(matrix);
  127.     matrix = t;
  128.     if (matrix != nil) {
  129.         matrix->Reference();
  130.     }
  131.     }
  132. }
  133.  
  134. Transformer* Painter::GetTransformer () {
  135.     return matrix;
  136. }
  137.  
  138. void Painter::MoveTo (int x, int y) {
  139.     curx = x;
  140.     cury = y;
  141. }
  142.  
  143. void Painter::GetPosition (int& x, int& y) {
  144.     x = curx;
  145.     y = cury;
  146. }
  147.  
  148. void Painter::SetOrigin (int x0, int y0) {
  149.     xoff = x0;
  150.     yoff = y0;
  151. }
  152.  
  153. void Painter::GetOrigin (int& x0, int& y0) {
  154.     x0 = xoff;
  155.     y0 = yoff;
  156. }
  157.  
  158. void Painter::Translate (float dx, float dy) {
  159.     if (dx != 0.0 || dy != 0.0) {
  160.     if (matrix == nil) {
  161.         matrix = new Transformer;
  162.     }
  163.     matrix->Translate(dx, dy);
  164.     }
  165. }
  166.  
  167. void Painter::Scale (float sx, float sy) {
  168.     if (sx != 1.0 || sy != 1.0) {
  169.     if (matrix == nil) {
  170.         matrix = new Transformer;
  171.     }
  172.     matrix->Scale(sx, sy);
  173.     }
  174. }
  175.  
  176. void Painter::Rotate (float angle) {
  177.     if (angle - int(angle) != 0.0 || int(angle) % 360 != 0) {
  178.     if (matrix == nil) {
  179.         matrix = new Transformer;
  180.     }
  181.     matrix->Rotate(angle);
  182.     }
  183. }
  184.  
  185. void Painter::CurveTo (Canvas* c,
  186.     Coord x0, Coord y0, Coord x1, Coord y1, Coord x2, Coord y2
  187. ) {
  188.     Curve(c, curx, cury, x0, y0, x1, y1, x2, y2);
  189.     curx = x2;
  190.     cury = y2;
  191. }
  192.  
  193. void Painter::Text (Canvas* c, const char* s) {
  194.     int len = strlen(s);
  195.     Text(c, s, len, curx, cury);
  196.     curx += font->Width(s, len);
  197. }
  198.  
  199. void Painter::Text (Canvas* c, const char* s, int len) {
  200.     Text(c, s, len, curx, cury);
  201.     curx += font->Width(s, len);
  202. }
  203.  
  204. void Painter::Text (Canvas* c, const char* s, Coord x, Coord y) {
  205.     Text(c, s, strlen(s), x, y);
  206. }
  207.  
  208. /*
  209.  * Spline drawing.
  210.  */
  211.  
  212. const int INITBUFSIZE = 100;
  213. const double SMOOTHNESS = 1.0;
  214.  
  215. static int llsize = 0;
  216. static int llcount = 0;
  217. static Coord* llx;
  218. static Coord* lly;
  219.  
  220. static void GrowBufs (Coord*& b1, Coord*& b2, int& cur) {
  221.     Coord* newb1;
  222.     Coord* newb2;
  223.     int newsize;
  224.  
  225.     if (cur == 0) {
  226.     cur = INITBUFSIZE;
  227.     b1 = new Coord[INITBUFSIZE];
  228.     b2 = new Coord[INITBUFSIZE];
  229.     } else {
  230.     newsize = cur * 2;
  231.     newb1 = new Coord[newsize];
  232.     newb2 = new Coord[newsize];
  233.     memmove(newb1, b1, newsize * sizeof(Coord));
  234.     memmove(newb2, b2, newsize * sizeof(Coord));
  235.     delete b1;
  236.     delete b2;
  237.     b1 = newb1;
  238.     b2 = newb2;
  239.     cur = newsize;
  240.     }
  241. }
  242.  
  243. inline void Midpoint (
  244.     double x0, double y0, double x1, double y1, double& mx, double& my
  245. ) {
  246.     mx = (x0 + x1) / 2.0;
  247.     my = (y0 + y1) / 2.0;
  248. }
  249.  
  250. inline void ThirdPoint (
  251.     double x0, double y0, double x1, double y1, double& tx, double& ty
  252. ) {
  253.     tx = (2*x0 + x1) / 3.0;
  254.     ty = (2*y0 + y1) / 3.0;
  255. }
  256.  
  257. inline boolean CanApproxWithLine (
  258.     double x0, double y0, double x2, double y2, double x3, double y3
  259. ) {
  260.     double triangleArea, sideSquared, dx, dy;
  261.  
  262.     triangleArea = x0*y2 - x2*y0 + x2*y3 - x3*y2 + x3*y0 - x0*y3;
  263.     triangleArea *= triangleArea;    // actually 4 times the area
  264.     dx = x3 - x0;
  265.     dy = y3 - y0;
  266.     sideSquared = dx*dx + dy*dy;
  267.     return triangleArea <= SMOOTHNESS * sideSquared;
  268. }
  269.  
  270. inline void AddLine (double x0, double y0, double x1, double y1) {
  271.     if (llcount >= llsize) {
  272.     GrowBufs(llx, lly, llsize);
  273.     }
  274.  
  275.     if (llcount == 0) {
  276.     llx[llcount] = round(x0);
  277.     lly[llcount] = round(y0);
  278.     ++llcount;
  279.     }
  280.     llx[llcount] = round(x1);
  281.     lly[llcount] = round(y1);
  282.     ++llcount;
  283. }
  284.  
  285. static void AddBezierCurve (
  286.     double x0, double y0, double x1, double y1,
  287.     double x2, double y2, double x3, double y3
  288. ) {
  289.     double midx01, midx12, midx23, midlsegx, midrsegx, cx;
  290.     double midy01, midy12, midy23, midlsegy, midrsegy, cy;
  291.     
  292.     Midpoint(x0, y0, x1, y1, midx01, midy01);
  293.     Midpoint(x1, y1, x2, y2, midx12, midy12);
  294.     Midpoint(x2, y2, x3, y3, midx23, midy23);
  295.     Midpoint(midx01, midy01, midx12, midy12, midlsegx, midlsegy);
  296.     Midpoint(midx12, midy12, midx23, midy23, midrsegx, midrsegy);
  297.     Midpoint(midlsegx, midlsegy, midrsegx, midrsegy, cx, cy);    
  298.  
  299.     if (CanApproxWithLine(x0, y0, midlsegx, midlsegy, cx, cy)) {
  300.         AddLine(x0, y0, cx, cy);
  301.     } else if (
  302.         (midx01 != x1) || (midy01 != y1) ||
  303.     (midlsegx != x2) || (midlsegy != y2) ||
  304.     (cx != x3) || (cy != y3)
  305.     ) {
  306.         AddBezierCurve(
  307.         x0, y0, midx01, midy01, midlsegx, midlsegy, cx, cy
  308.     );
  309.     }
  310.     if (CanApproxWithLine(cx, cy, midx23, midy23, x3, y3)) {
  311.         AddLine(cx, cy, x3, y3);
  312.     } else if (
  313.         (cx != x0) || (cy != y0) ||
  314.     (midrsegx != x1) || (midrsegy != y1) ||
  315.     (midx23 != x2) || (midy23 != y2)
  316.     ) {        
  317.         AddBezierCurve(
  318.         cx, cy, midrsegx, midrsegy, midx23, midy23, x3, y3
  319.     );
  320.     }
  321. }
  322.  
  323. static void CalcBSpline (
  324.     Coord cminus1x, Coord cminus1y, Coord cx, Coord cy,
  325.     Coord cplus1x, Coord cplus1y, Coord cplus2x, Coord cplus2y
  326. ) {
  327.     double p0x, p1x, p2x, p3x, tempx,
  328.        p0y, p1y, p2y, p3y, tempy;
  329.     
  330.     ThirdPoint(
  331.         double(cx), double(cy), double(cplus1x), double(cplus1y), p1x, p1y
  332.     );
  333.     ThirdPoint(
  334.         double(cplus1x), double(cplus1y), double(cx), double(cy), p2x, p2y
  335.     );
  336.     ThirdPoint(
  337.         double(cx), double(cy), double(cminus1x), double(cminus1y),
  338.     tempx, tempy
  339.     );
  340.     Midpoint(tempx, tempy, p1x, p1y, p0x, p0y);
  341.     ThirdPoint(
  342.         double(cplus1x), double(cplus1y), double(cplus2x), double(cplus2y),
  343.     tempx, tempy
  344.     );
  345.     Midpoint(tempx, tempy, p2x, p2y, p3x, p3y);
  346.     
  347.     AddBezierCurve(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y);
  348. }
  349.  
  350. void CreateOpenLineList (Coord *cpx, Coord *cpy, int cpcount) {
  351.     int cpi;
  352.  
  353.     llcount = 0;
  354.     CalcBSpline(
  355.     cpx[0], cpy[0], cpx[0], cpy[0], cpx[0], cpy[0], cpx[1], cpy[1]
  356.     );
  357.     CalcBSpline(
  358.     cpx[0], cpy[0], cpx[0], cpy[0], cpx[1], cpy[1], cpx[2], cpy[2]
  359.     );
  360.  
  361.     for (cpi = 1; cpi < cpcount - 2; ++cpi) {
  362.     CalcBSpline(
  363.         cpx[cpi - 1], cpy[cpi - 1], cpx[cpi], cpy[cpi],
  364.         cpx[cpi + 1], cpy[cpi + 1], cpx[cpi + 2], cpy[cpi + 2]
  365.     );
  366.     }
  367.     CalcBSpline(
  368.     cpx[cpi - 1], cpy[cpi - 1], cpx[cpi], cpy[cpi],
  369.     cpx[cpi + 1], cpy[cpi + 1], cpx[cpi + 1], cpy[cpi + 1]
  370.     );
  371.     CalcBSpline(
  372.     cpx[cpi], cpy[cpi], cpx[cpi + 1], cpy[cpi + 1],
  373.     cpx[cpi + 1], cpy[cpi + 1], cpx[cpi + 1], cpy[cpi + 1]
  374.     );
  375. }
  376.  
  377. void CreateClosedLineList (Coord *cpx, Coord *cpy, int cpcount) {
  378.     int cpi;
  379.  
  380.     llcount = 0;
  381.     CalcBSpline(
  382.     cpx[cpcount - 1], cpy[cpcount - 1], cpx[0], cpy[0], 
  383.     cpx[1], cpy[1], cpx[2], cpy[2]
  384.     );
  385.  
  386.     for (cpi = 1; cpi < cpcount - 2; ++cpi) {
  387.     CalcBSpline(
  388.         cpx[cpi - 1], cpy[cpi - 1], cpx[cpi], cpy[cpi],
  389.         cpx[cpi + 1], cpy[cpi + 1], cpx[cpi + 2], cpy[cpi + 2]
  390.         );
  391.     }
  392.     CalcBSpline(
  393.     cpx[cpi - 1], cpy[cpi - 1], cpx[cpi], cpy[cpi],
  394.     cpx[cpi + 1], cpy[cpi + 1], cpx[0], cpy[0]
  395.     );
  396.     CalcBSpline(
  397.     cpx[cpi], cpy[cpi], cpx[cpi + 1], cpy[cpi + 1],
  398.     cpx[0], cpy[0], cpx[1], cpy[1]
  399.     );
  400. }
  401.  
  402. static int bufsize = 0;
  403. static Coord* bufx, * bufy;
  404.  
  405. static void CheckBufs (Coord*& b1, Coord*& b2, int& cur, int desired) {
  406.     if (cur < desired) {
  407.     if (cur == 0) {
  408.         cur = max(INITBUFSIZE, desired);
  409.     } else {
  410.         delete b1;
  411.         delete b2;
  412.         cur = max(cur * 2, desired);
  413.     }
  414.     b1 = new Coord[cur];
  415.     b2 = new Coord[cur];
  416.     }
  417. }
  418.  
  419. void Painter::Curve (
  420.     Canvas* c, Coord x0, Coord y0, Coord x1, Coord y1,
  421.     Coord x2, Coord y2, Coord x3, Coord y3
  422. ) {
  423.     Coord tx0, ty0, tx1, ty1, tx2, ty2, tx3, ty3;
  424.     
  425.     llcount = 0;
  426.     Map(c, x0, y0, tx0, ty0);
  427.     Map(c, x1, y1, tx1, ty1);
  428.     Map(c, x2, y2, tx2, ty2);
  429.     Map(c, x3, y3, tx3, ty3);
  430.     AddBezierCurve(tx0, ty0, tx1, ty1, tx2, ty2, tx3, ty3);
  431.     MultiLineNoMap(c, llx, lly, llcount);
  432. }
  433.  
  434. void Painter::BSpline (Canvas* c, Coord x[], Coord y[], int count) {
  435.     CheckBufs(bufx, bufy, bufsize, count);
  436.     MapList(c, x, y, count, bufx, bufy);
  437.     if (count < 3) {
  438.         MultiLineNoMap(c, bufx, bufy, count);
  439.     } else {
  440.     CreateOpenLineList(bufx, bufy, count);
  441.     MultiLineNoMap(c, llx, lly, llcount);
  442.     }
  443. }
  444.  
  445. void Painter::ClosedBSpline (Canvas* c, Coord x[], Coord y[], int count) {
  446.     CheckBufs(bufx, bufy, bufsize, count);
  447.     MapList(c, x, y, count, bufx, bufy);
  448.     if (count < 3) {
  449.         MultiLineNoMap(c, bufx, bufy, count);
  450.     } else {
  451.         CreateClosedLineList(bufx, bufy, count);
  452.         MultiLineNoMap(c, llx, lly, llcount);
  453.     }
  454. }
  455.  
  456. void Painter::FillBSpline (Canvas* c, Coord x[], Coord y[], int count) {
  457.     CheckBufs(bufx, bufy, bufsize, count);
  458.     MapList(c, x, y, count, bufx, bufy);
  459.     if (count < 3) {
  460.         FillPolygonNoMap(c, bufx, bufy, count);
  461.     } else {
  462.         CreateClosedLineList(bufx, bufy, count);
  463.         FillPolygonNoMap(c, llx, lly, llcount);
  464.     }
  465. }
  466.  
  467. void Painter::Map (Canvas* c, Coord x, Coord y, short& sx, short& sy) {
  468.     Coord cx, cy;
  469.  
  470.     Map(c, x, y, cx, cy);
  471.     sx = short(cx);
  472.     sy = short(cy);
  473. }
  474.  
  475. const float axis = 0.42;
  476. const float seen = 1.025;
  477.  
  478. void Painter::Ellipse (Canvas* c, Coord cx, Coord cy, int r1, int r2) {
  479.     float px1, py1, px2, py2, x[8], y[8];
  480.  
  481.     px1 = float(r1)*axis; py1 = float(r2)*axis;
  482.     px2 = float(r1)*seen; py2 = float(r2)*seen;
  483.     x[0] = cx + px1;    y[0] = cy + py2;
  484.     x[1] = cx - px1;    y[1] = y[0];
  485.     x[2] = cx - px2;    y[2] = cy + py1;
  486.     x[3] = x[2];    y[3] = cy - py1;
  487.     x[4] = x[1];    y[4] = cy - py2;
  488.     x[5] = x[0];    y[5] = y[4];
  489.     x[6] = cx + px2;    y[6] = y[3];
  490.     x[7] = x[6];    y[7] = y[2];
  491.  
  492.     CheckBufs(bufx, bufy, bufsize, 8);
  493.     MapList(c, (float*) x, (float*) y, 8, bufx, bufy);
  494.     CreateClosedLineList(bufx, bufy, 8);
  495.     MultiLineNoMap(c, llx, lly, llcount);
  496. }
  497.  
  498. void Painter::FillEllipse (Canvas* c, Coord cx, Coord cy, int r1, int r2) {
  499.     float px1, py1, px2, py2, x[8], y[8];
  500.  
  501.     px1 = float(r1)*axis; py1 = float(r2)*axis;
  502.     px2 = float(r1)*seen; py2 = float(r2)*seen;
  503.     x[0] = cx + px1;    y[0] = cy + py2;
  504.     x[1] = cx - px1;    y[1] = y[0];
  505.     x[2] = cx - px2;    y[2] = cy + py1;
  506.     x[3] = x[2];    y[3] = cy - py1;
  507.     x[4] = x[1];    y[4] = cy - py2;
  508.     x[5] = x[0];    y[5] = y[4];
  509.     x[6] = cx + px2;    y[6] = y[3];
  510.     x[7] = x[6];    y[7] = y[2];
  511.  
  512.     CheckBufs(bufx, bufy, bufsize, 8);
  513.     MapList(c, (float*) x, (float*) y, 8, bufx, bufy);
  514.     CreateClosedLineList(bufx, bufy, 8);
  515.     FillPolygonNoMap(c, llx, lly, llcount);
  516. }
  517.  
  518. #ifdef _3D
  519.  
  520. Painter3D::Painter3D() : () {
  521.   fg[0] = fg[1] = fg[2] = fg[3] = nil;
  522.   SetColors3D();
  523. }
  524.  
  525. Painter3D::Painter3D(Painter *p) : (p) {
  526.   fg[0] = fg[1] = fg[2] = fg[3] = nil;
  527.   CopyState(p);
  528. }
  529.  
  530. Painter3D::~Painter3D() {
  531.   Unref(fg[0]);
  532.   Unref(fg[1]);
  533.   Unref(fg[2]);
  534.   Unref(fg[3]);
  535. }
  536.  
  537. void Painter3D::CopyState(Painter* p) {
  538.   Copy(p);
  539.   SetColors3D();
  540. }
  541.  
  542. void Painter3D::SetColors3D() {
  543.     int r,g,b;
  544.  
  545.     background->Intensities(r,g,b);
  546.     float v = (max(max(r,g),b)/65535.0);    // intensity of the background (HSV model)
  547.     float v0 = 1.5*v < 1.0 ? 1.5 : 1.0/v;    // intensity of upper bar
  548.     float v1 = 1.3*v < 1.0 ? 1.3 : 1.0/v;    // intensity of right bar
  549.     float v2 = 0.5;                // intensity of left and lower bar
  550.     float v3 = 0.9;
  551.     Unref(fg[0]);
  552.     Unref(fg[1]);
  553.     Unref(fg[2]);
  554.     Unref(fg[3]);
  555.     fg[0] = new Color((int)(v0*r), (int)(v0*g), (int)(v0*b));
  556.     fg[1] = new Color((int)(v1*r), (int)(v1*g), (int)(v1*b));
  557.     fg[2] = new Color((int)(v2*r), (int)(v2*g), (int)(v2*b));
  558.     fg[3] = new Color((int)(v3*r), (int)(v3*g), (int)(v3*b));
  559.     fg[0]->Reference();
  560.     fg[1]->Reference();
  561.     fg[2]->Reference();
  562.     fg[3]->Reference();
  563. }
  564.  
  565. void Painter3D::SetColors3D(Color* f1, Color* f2, Color* f3, Color* f4) {
  566.     fg[0]=f1; fg[1]=f2; fg[2]=f3; fg[3]=f4;
  567. }
  568.  
  569. void Painter3D::UseColor3D(char index) {
  570.     SetColors(fg[index],background);
  571. }
  572.  
  573. void Painter3D::InvertColors() {
  574.     SetColors(background,foreground);
  575. }
  576.  
  577. void Painter3D::Border(Canvas* c, Coord x1, Coord y1, Coord x2, Coord y2,char inout,char width,char flag)
  578. { Coord x[4],y[4];
  579.   int d=width; x2++; y1--;
  580.   if (flag&1)
  581.   { x[0]=x1;        y[0]=y2;
  582.     x[1]=x2;        y[1]=y2;
  583.     x[2]=x2-d;      y[2]=y2-d;
  584.     x[3]=x1+d;      y[3]=y2-d;
  585.     UseColor3D(inout ? 0:2);
  586.     FillPolygon(c,x,y,4); }
  587.  
  588.   if (flag&2)
  589.   { x[0]=x2;        y[0]=y2;
  590.     x[1]=x2;        y[1]=y1;
  591.     x[2]=x2-d;      y[2]=y1+d;
  592.     x[3]=x2-d;      y[3]=y2-d;
  593.     UseColor3D(inout ? 1:2);
  594.     FillPolygon(c,x,y,4); }
  595.  
  596.   if (flag&4)
  597.   { x[0]=x2;        y[0]=y1;
  598.     x[1]=x1;        y[1]=y1;
  599.     x[2]=x1+d;      y[2]=y1+d;
  600.     x[3]=x2-d;      y[3]=y1+d;
  601.     UseColor3D(inout ? 2:0);
  602.     FillPolygon(c,x,y,4); }
  603.  
  604.   if (flag&8)
  605.   { x[0]=x1;        y[0]=y1;
  606.     x[1]=x1;        y[1]=y2;
  607.     x[2]=x1+d;      y[2]=y2-d;
  608.     x[3]=x1+d;      y[3]=y1+d;
  609.     UseColor3D(inout ? 2:1);
  610.     FillPolygon(c,x,y,4); }}
  611.  
  612. void Painter3D::Border(Canvas* c,char inout,char width,char flag)
  613. { Border(c,0,0,c->Width()-1,c->Height()-1,inout,width,flag); }
  614.  
  615. #endif
  616.